package com.zkgengkun.interceptor;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zkgengkun.constant.LoginConstants;
import com.zkgengkun.constant.MapConstants;
import com.zkgengkun.constant.SysConstants;
import com.zkgengkun.domain.User;
import com.zkgengkun.support.component.LoginSession;
import com.zkgengkun.support.json.Jacksons;
import com.zkgengkun.support.util.CookieUtils;
import com.zkgengkun.support.util.JedisUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;

/**
 * @author gengshikun
 * @date 2016/11/25
 */
public class LoginInterceptor implements HandlerInterceptor {

    private static final Logger logger = LoggerFactory.getLogger(LoginInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 设置当前登录人
        Map<String, Object> cookieMap = CookieUtils.cookies2Map(request);
        String loginToken = (String) cookieMap.get(LoginConstants.CUSTOMER_LOGIN_TOKEN);

        User user = null;
        boolean haveLogin = false;
        if (StringUtils.isNotBlank(loginToken)) {
            user = Jacksons.json().fromJsonToObject(
                    JedisUtil.getInstance().STRINGS.get(LoginConstants.CUSTOMER_LOGIN_REDIS_KEY + loginToken), User.class);
            if (null != user) {
                haveLogin = true;
            }
        }
        LoginSession.setUser(user);

        // url_pass
        String contextPath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath();
        String url = request.getRequestURI().toString();
        if (isMatchUrl(url, MapConstants.URL_PASS_MAP) || StringUtils.isEmpty(url)) {
            return true;
        }

        if (haveLogin) { //用户已登录
            //刷新用户登陆时间
            JedisUtil.getInstance().KEYS.expire(LoginConstants.CUSTOMER_LOGIN_REDIS_KEY + loginToken, LoginConstants.CUSTOMER_LOGIN_OVER_TIME);
            //刷新cookie
            Cookie cookie = new Cookie(LoginConstants.CUSTOMER_LOGIN_TOKEN, loginToken);
            cookie.setMaxAge(LoginConstants.CUSTOMER_LOGIN_OVER_TIME);
            cookie.setPath("/");
            response.addCookie(cookie);
            return true;
        } else { // 用户未登录
            logger.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>登录拦截 ...>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
            if (request.getHeader("x-requested-with") != null && request.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest")) {
                // 异步请求
                this.ajaxRequestErrorResp(response, request);
            } else {
                // 非异步请求
                response.sendRedirect(contextPath + "/auth/n/login?returnUrl=" + URLEncoder.encode(this.getReturnUrl(request), SysConstants.URL_CHARSET));//未登录
            }
            return false;
        }
    }

    private boolean isMatchUrl(String url, Map<String, String> sysCacheMap) {
        if ("/".equals(url)) {    //首页
            return true;
        }

        //检查noPass
        for (Map.Entry<String, String> entry : sysCacheMap.entrySet()) {
            String furl = entry.getKey();
            String type = entry.getValue();
            if (furl.equals(url)) {
                if (type.equals("noPass")) {
                    return false;
                }
            }
        }

        boolean isMtch = false;
        for (Map.Entry<String, String> entry : sysCacheMap.entrySet()) {

            String furl = entry.getKey();
            String[] furlArray = furl.split("/");
            String[] urlArray = url.split("/");

            int sum = 0;
            List<Integer> matcher = Lists.newArrayList();
            for (int i = 0; i < furlArray.length; i++) {
                String node = furlArray[i];
                if (!node.equals("**") && StringUtils.isNotEmpty(node)) {
                    sum++;
                    for (int j = 0; j < urlArray.length; j++) {
                        String urlNode = urlArray[j];
                        if (urlNode.equals(node)) {
                            matcher.add(i);
                        }
                    }
                }
            }
            if (matcher.size() >= sum) {
                isMtch = true;
                for (int i = 0; i < matcher.size(); i++) {
                    int indexI = matcher.get(i);
                    for (int j = i + 1; j < matcher.size(); j++) {
                        int indexJ = matcher.get(j);
                        if (indexJ < indexI) {
                            return false;
                        }
                    }
                }
            }

        }
        return isMtch;
    }

    private void ajaxRequestErrorResp(HttpServletResponse response, HttpServletRequest request) throws IOException {
        response.setContentType("application/json; charset=UTF-8");

        Map<String, Object> resultMap = Maps.newHashMap();
        resultMap.put("success", false);
        resultMap.put("errorCode", LoginConstants.ERROR_CODE_0003); //未登录错误码
        resultMap.put("errorMsg", "用户未登录");    //未登录

        String url = request.getRequestURI().toString();
        if (this.isMatchUrl(url, MapConstants.URL_SPECIAL_MAP)) {
            resultMap.put("returnUrl", URLEncoder.encode(request.getHeader("Referer"), SysConstants.URL_CHARSET));
        } else {
            resultMap.put("returnUrl", URLEncoder.encode(this.getReturnUrl(request), SysConstants.URL_CHARSET));
        }
        response.getWriter().write(Jacksons.json().fromObjectToJson(resultMap));
    }

    /**
     * 获得returnUrl
     *
     * @param request
     * @return
     */
    private String getReturnUrl(HttpServletRequest request) {
        String currentUrl =
                request.getScheme() + "://" + request.getHeader("host")
                        + request.getContextPath()
                        + request.getServletPath()
                        + (null != request.getQueryString() ? "?" + request.getQueryString() : "");
        return currentUrl;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) throws Exception {

    }
}
